package org.streets.workflow.engine.mem;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.streets.workflow.engine.ISyncRouter;
import org.streets.workflow.engine.event.INodeEventListener;
import org.streets.workflow.engine.plugin.INodeNetExtension;
import org.streets.workflow.model.net.WFEndNode;
import org.streets.workflow.model.net.WFSyncRouter;


/**
 * @author 非也,nychen2000@163.com
 * 
 */
public class EndNode extends AbstractNode implements ISyncRouter {

    public transient static final Log log = LogFactory.getLog(EndNode.class);
    public static final String ExtensionTargetName = "org.streets.workflow.EndNode";
    public static final String ExtensionPointNodeEventListener = "NodeEventListener";

    public static final List<String> ExtensionPointNames = new ArrayList<String>();
    
    static {
        ExtensionPointNames.add(ExtensionPointNodeEventListener);
    }
    private int volume = 0;// 即节点的容量
    private int tokenValue = 0;
    private WFEndNode endNode = null;

    public EndNode(WFEndNode model) {
        this.type = NodeType.End;
        this.endNode = model;
        this.volume = this.endNode.getEnteringTransitions().size();
    }

    public String getNodeId() {
        return this.endNode.getId();
    }

    @SuppressWarnings("unchecked")
    public WFSyncRouter getNodeModel() {
        return this.endNode;
    }
    /*
     * (non-Javadoc)
     *
     * @see org.fireflow.kenel.ISynchronizerInstance#getTokens()
     */
    public int getValue() {
        return tokenValue;
    }
    /*
     * (non-Javadoc)
     *
     * @see org.fireflow.kenel.ISynchronizerInstance#setTokens(int)
     */
    public void setValue(int tokenNum) {
        this.tokenValue = tokenNum;
    }
    /*
     * (non-Javadoc)
     *
     * @see org.fireflow.kenel.ISynchronizerInstance#getVolume()
     */
    public int getVolume() {
        return volume;
    }
    /*
     * (non-Javadoc)
     *
     * @see org.fireflow.kenel.ISynchronizerInstance#setVolume(int)
     */
    public void setVolume(int k) {
        this.volume = k;
    }
//
//    /*
//     * (non-Javadoc)
//     *
//     * @see org.fireflow.kenel.IPTNetExecutor#fire(org.fireflow.kenel.RuntimeContext,
//     *      org.fireflow.kenel.ITransitionInstance)
//     */
//    public void fire(IToken tk) throws WorkflowException {
//    	IJoinPoint joinPoint = null;
//        synchronized (this) {
//            tk.setNodeId(this.getRouterModel().getNodeId());
//            log.debug("The weight of the Entering TransitionInstance is " + tk.getValue());
//            // 触发TokenEntered事件
//            NodeEvent event1 = new NodeEvent(this);
//            event1.setToken(tk);
//            event1.setEventType(NodeEvent.NODEINSTANCE_TOKEN_ENTERED);
//            fireNodeEvent(event1);
//
//            //汇聚检查
//            joinPoint = ((ProcessInstance) tk.getCurrentProcessInstance()).createJoinPoint(this, tk);// JoinPoint由谁生成比较好？
//            int value = joinPoint.getValue();
//
//            log.debug("The volume of " + this.toString() + " is " + volume);
//            log.debug("The value of " + this.toString() + " is " + value);
//            if (value > volume) {
//            	WorkflowException exception = new WorkflowException(tk.getCurrentProcessInstance(),
//                        this.getRouterModel(),
//                        "Error:The token count of the synchronizer-instance can NOT be  greater than  it's volumn  ");
//                throw exception;
//            }
//            if (value < volume) {// 如果Value小于容量则继续等待其他弧的汇聚。
//                return;
//            }
//        }
//
//        IProcessInstance processInstance = tk.getCurrentProcessInstance();
//        NodeEvent event2 = new NodeEvent(this);
//        event2.setToken(tk);
//        event2.setEventType(NodeEvent.NODEINSTANCE_FIRED);
//        fireNodeEvent(event2);
//        
//        //在此事件监听器中，删除原有的token
//        NodeEvent event4 = new NodeEvent(this);
//        event4.setToken(tk);
//        event4.setEventType(NodeEvent.NODEINSTANCE_LEAVING);
//        fireNodeEvent(event4);
//        
//        //首先必须检查是否有满足条件的循环
//        boolean doLoop = false;//表示是否有满足条件的循环，false表示没有，true表示有。
//
//        if (joinPoint.getAlive()) {
//            IToken tokenForLoop = null;
//
//                tokenForLoop = new Token(); // 产生新的token
//                tokenForLoop.setAlive(joinPoint.getAlive());
//                tokenForLoop.setCurrentProcessInstance(processInstance);
//                tokenForLoop.setStepNumber(joinPoint.getStepNumber()-1);
//                tokenForLoop.setFromActivityId(joinPoint.getFromActivityId());
//
//            for (int i = 0; i < this.leavingLoopInstances.size(); i++) {
//            	
//                ILoop loopInstance = this.leavingLoopInstances.get(i);
//
//                doLoop = loopInstance.take(tokenForLoop);
//                if (doLoop) {
//                    break;
//                }
//            }
//        }
//
//        if (!doLoop){
//            NodeEvent event3 = new NodeEvent(this);
//            event3.setToken(tk);
//            event3.setEventType(NodeEvent.NODEINSTANCE_COMPLETED);
//            fireNodeEvent(event3);
//        }
//        
////        NodeInstanceEvent event4 = new NodeInstanceEvent(this);
////        event4.setToken(tk);
////        event4.setEventType(NodeInstanceEvent.NODEINSTANCE_LEAVING);
////        fireNodeLeavingEvent(event4);
//    }

    /*
     * (non-Javadoc)
     *
     * @see org.fireflow.kenel.plugin.IPlugable#getExtensionPointNames()
     */
    public List<String> getExtensionPointNames() {
        return ExtensionPointNames;
    }

    /*
     * (non-Javadoc)
     *
     * @see org.fireflow.kenel.plugin.IPlugable#getExtensionTargetName()
     */
    public String getExtensionTargetName() {
        return ExtensionTargetName;
    }

    /*
     * (non-Javadoc)
     *
     * @see org.fireflow.kenel.plugin.IPlugable#registExtension(org.fireflow.kenel.plugin.IKenelExtension)
     */
    public void register(INodeNetExtension extension)
            throws RuntimeException {
        if (!ExtensionTargetName.equals(extension.getExtentionTargetName())) {
            throw new RuntimeException(
                    "Error:When construct the EndNodeInstance,the Extension_Target_Name is mismatching");
        }
        
        if (ExtensionPointNodeEventListener.equals(extension.getExtentionPointName())) {
            if (extension instanceof INodeEventListener) {
                this.eventListeners.add((INodeEventListener) extension);
            } else {
                throw new RuntimeException(
                        "Error:When construct the EndNodeInstance,the extension MUST be a instance of INodeInstanceEventListener");
            }
        }
    }

    public String toString() {
        return "EndNodeInstance_4_[" + endNode.getId() + "]";
    }
}
